
#pragma once
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <functional>

using func_t = std::function<void*(void*)>;

class Thread
{
public:
    typedef enum
    {
        NEW = 0,
        RUNNING,
        EXITED
    } ThreadStatus;
public:
    Thread(int num, func_t func, void* args) : _tid(num), _status(NEW), _func(func), _args(args)
    {
        char name[128];
        snprintf(name, sizeof(name), "thread-%d", num);
        _name = name;
    }
    int threadStatus()
    {
        return _status;
    }
    std::string threadName()
    {
        return _name;
    }
    pthread_t threadTid()
    {
        if(_status == RUNNING)
            return _tid;
        else
        {
            std::cout << "thread not running.....\n";
            return 0;
        }
    }
    static void* runHepler(void* args)
    {
        Thread* ts = (Thread*)args;
        (*ts)();
    }
    void operator()()
    {
        if(_func) _func(_args);
    }
    void threadRun()
    {
        int n = pthread_create(&_tid, nullptr, runHepler, this);
        if(n != 0) exit(-1);
        _status = RUNNING;
    }
    void threadJoin()
    {
        int n = pthread_join(_tid, nullptr);
        if(n != 0)
        {
            std::cerr << "main thread join failed " << _name << std::endl;
            exit(-1);
        }
        _status = EXITED;
    }
    ~Thread(){}
private:
    pthread_t _tid;
    std::string _name;
    func_t _func;
    void* _args;
    ThreadStatus _status;
};